package com.dbapp.shopping.controller;

import com.dbapp.shopping.domain.Good;
import com.dbapp.shopping.domain.GoodOwner;
import com.dbapp.shopping.domain.Record;
import com.dbapp.shopping.domain.User;
import com.dbapp.shopping.service.Service;
import com.dbapp.shopping.storage.StorageService;
import com.dbapp.shopping.storage.StorageFileNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import javax.transaction.Transactional;
import java.nio.file.Paths;
import java.security.Principal;
import java.util.Optional;

@Controller
public class TradeController {

    private Service service;
    private StorageService storageService;

    @Autowired
    public TradeController(Service service, StorageService storageService) {
        this.service = service;
        this.storageService = storageService;
    }

    @GetMapping("/")
    public String homepage(Model model, Principal principal) {
        Authentication authentication = (Authentication) principal;
        if (principal != null && authentication.isAuthenticated()) {
            model.addAttribute("status", true);
            model.addAttribute("user", (User) authentication.getPrincipal());
        } else {
            model.addAttribute("status", false);
        }

        model.addAttribute("goods", service.getAllGoods());

        return "home";
    }

    @GetMapping("/new")
    public String showNewGood(Model model, @AuthenticationPrincipal User user) {
        model.addAttribute("user", user)
                .addAttribute("status", true)
                .addAttribute("get", true)
                .addAttribute("checkgoodsname", true)
                .addAttribute("checkgoodsdescription", true)
                .addAttribute("checkgoodsstock", true)
                .addAttribute("checkgoodsprice", true)
                .addAttribute("checkgoodsimg", true);
        return "upload";
    }

    @ModelAttribute(name = "goodowner")
    public GoodOwner goodOwner() {
        return new GoodOwner();
    }

    @PostMapping("/new")
    public String getNewGood(@ModelAttribute GoodOwner goodOwner, Model model, @AuthenticationPrincipal User user,
                             @RequestParam("avataruri") MultipartFile img, String name, String description, String stock, String price) {
        model.addAttribute("user", user)
                .addAttribute("get", false)
                .addAttribute("status", true)
                .addAttribute("checkgoodsname", true)
                .addAttribute("checkgoodsdescription", true)
                .addAttribute("checkgoodsstock", true)
                .addAttribute("checkgoodsprice", true)
                .addAttribute("checkgoodsimg", true);
        Boolean flag = false;
        String extension = StringUtils.getFilenameExtension(img.getOriginalFilename());
        if(img.isEmpty())
        {
            model.addAttribute("checkgoodsimg", false);
            flag = true;
        }
        if(!img.isEmpty() && !(extension.equals("jpg") || extension.equals("jpeg") || extension.equals("png")))
        {
            model.addAttribute("checkgoodsimg", false);
            flag = true;
        }
        if(name.isEmpty())
        {
            model.addAttribute("checkgoodsname", false);
            flag = true;
        }
        if(description.isEmpty())
        {
            model.addAttribute("checkgoodsdescription", false);
            flag = true;
        }
        if(stock.isEmpty() || !service.isStock(stock))
        {
            model.addAttribute("checkgoodsstock", false);
            flag = true;
        }
        if(price.isEmpty() || !service.isPrice(price))
        {
            model.addAttribute("checkgoodsprice", false);
            flag = true;
        }
        if(flag)
            return "upload";
        Good good = new Good(name, description, Long.valueOf(stock), Double.valueOf(price));
        Good saved = service.saveGood(good);
        String newName = saved.getId().toString() + "." + extension;
        storageService.storeGoodsImg(img, newName);
        saved.setAvataruri("/PJImg/goodsImg/" + newName);
        saved = service.saveGood(good);
        goodOwner.setUser(user);
        goodOwner.setGood(saved);
        service.saveGoodOwner(goodOwner);
        return "redirect:/profile=" + user.getUsername();
    }

    @ExceptionHandler(StorageFileNotFoundException.class)
    public ResponseEntity<?> handleStorageFileNotFound(StorageFileNotFoundException exc) {
        return ResponseEntity.notFound().build();
    }

    @GetMapping("/goods={id}")
    public String getGoodInfo(@PathVariable("id") Long id, Model model, Principal principal) {
        Authentication authentication = (Authentication) principal;
        if (principal != null && authentication.isAuthenticated()) {
            model.addAttribute("status", true);
            model.addAttribute("user", (User) authentication.getPrincipal());
        } else {
            Optional<User> user = service.getUserById(1L);
            model.addAttribute("status", false)
                    .addAttribute("user", user.get());
        }
        Optional<Good> good = service.getGoodById(id);
        if (good.isPresent()) {
            Optional<GoodOwner> go = service.getGoodOwnerByGood(good.get());
            model.addAttribute("good", good.get());
            if(go.isPresent())
            {
                model.addAttribute("seller", go.get().getUser());
                return "goods-info";
            }
            else
                return "error";
        } else {
            return "error";
        }
    }

    @GetMapping("/pay")
    public String paymentPage(Model model, Long id, Principal principal) {
        Authentication authentication = (Authentication) principal;
        if (principal != null && authentication.isAuthenticated()) {
            model.addAttribute("status", true);
            model.addAttribute("user", (User) authentication.getPrincipal());
        } else {
            model.addAttribute("status", false);
            return "redirect:/login";
        }
        Optional<Good> good = service.getGoodById(id);
        if(good.isPresent())
        {
            model.addAttribute("currentgood", good.get())
                    .addAttribute("checkprice", true)
                    .addAttribute("confirm", false)
                    .addAttribute("numnull", false)
                    .addAttribute("over", false);
            return "payment";
        }
        else
            return "error";
    }

    @PostMapping("/confirm")
    public String processConfirm(Model model, Long id, String number, @AuthenticationPrincipal User user) {
        model.addAttribute("user", user)
                .addAttribute("get", false)
                .addAttribute("status", true)
                .addAttribute("checkprice", true)
                .addAttribute("confirm", true);
        Optional<Good> good = service.getGoodById(id);
        Double cost = 0.00;
        if (good.isPresent()) {
            Good g = good.get();
            if(number.isEmpty() || !service.isStock(number))
            {
                model.addAttribute("numnull", true)
                        .addAttribute("confirm", false);
            }
            else if(Long.valueOf(number) > g.getStock())
            {
                model.addAttribute("over", true)
                        .addAttribute("confirm", false);
            }
            else {
                cost = g.getPrice() * Long.valueOf(number).doubleValue();
                model.addAttribute("number", Long.valueOf(number));
            }
            model.addAttribute("cost", cost)
                    .addAttribute("currentgood", g);
            return "payment";
        }
        else
            return "error";
    }

    @PostMapping("/confirmed-pay")
    public String processPayment(Model model, Double recharge, Long id, Long number, Double cost, @AuthenticationPrincipal User user) {
        model.addAttribute("user", user)
                .addAttribute("get", false)
                .addAttribute("status", true)
                .addAttribute("checkprice", true)
                .addAttribute("numnull", false)
                .addAttribute("over", false)
                .addAttribute("confirm", true)
                .addAttribute("cost", cost);
        Optional<Good> good = service.getGoodById(id);
        if (good.isPresent()) {
            Good g = good.get();
            if(cost > user.getBalance())
            {
                model.addAttribute("checkprice", false)
                        .addAttribute("currentgood", g);
                return "payment";
            }
            user.setBalance(user.getBalance() - cost);//减少
            User savedUser = service.saveUser(user);
            g.setStock(g.getStock() - number);
            if(g.getStock() == 0)
                g.setDisplay(false);
            //查找对应的卖家信息
            Good saved = service.saveGood(g);
            User seller = service.findSeller(saved);
            seller.setBalance(seller.getBalance() + cost);
            Record rec = new Record(saved, seller, user, number);
            service.saveRecord(rec);
            model.addAttribute("user", savedUser);
            return "redirect:/profile=" + user.getUsername();
        }
        else
            return "error";
    }

    @PostMapping("/delete-goods")
    @Transactional
    public String processDeleteGoods(Model model, Long id, @AuthenticationPrincipal User user)
    {
        model.addAttribute("user", user)
                .addAttribute("get", false)
                .addAttribute("status", true);
        service.deleteGoodsById(id);
        return "redirect:/profile=" + user.getUsername();
    }

    @PostMapping("/delete-order")
    @Transactional
    public String processDeleteOrder(Model model, Long id, @AuthenticationPrincipal User user)
    {
        model.addAttribute("user", user)
                .addAttribute("get", false)
                .addAttribute("status", true);
        service.deleteOrder(id);
        return "redirect:/profile=" + user.getUsername();
    }
}
